package com.cooper.java.scraper;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * User: cooperlee
 * Date: 11/15/12
 * Time: 9:31 AM
 * To change this template use File | Settings | File Templates.
 */
public class RegExp {

    private Scraper scraper;

    /*
    public RegExp(Scraper scraper, XmlPullParser xml) {
        this.scraper = scraper;
        input = xml.getAttributeValue(null, "input");
        output = xml.getAttributeValue(null, "output");
        String destStr = xml.getAttributeValue(null, "dest");
        if (destStr.trim().charAt(destStr.length() - 1) == '+') {
            addDest = true;
            destStr = destStr.trim().substring(0, destStr.length() - 1);
        }
        dest = Integer.parseInt(destStr);
        conditional = xml.getAttributeValue(null, "conditional");
    }    */

    public RegExp(Scraper scraper, String input, String output, String destStr,String conditional){
        this.scraper = scraper;
        this.input = input;
        this.output = output;
        if (destStr.trim().charAt(destStr.length() - 1) == '+') {
            addDest = true;
            destStr = destStr.trim().substring(0, destStr.length() - 1);
        }
        dest = Integer.parseInt(destStr);
        this.conditional = conditional;
    }

    public String input;
    public String output;
    public Integer dest;
    public boolean addDest = false;
    public String conditional;
    public Exp exp;

    private RegExp parentRegExp;
    private List<RegExp> subRegExps = new ArrayList<RegExp>();

    public RegExp getParentRegExp() {
        return parentRegExp;
    }

    public List<RegExp> getSubRegExps() {
        return subRegExps;
    }

    public RegExp addSubRegExp(RegExp subRegExp) {
        subRegExps.add(subRegExp);
        subRegExp.parentRegExp = this;
        return subRegExp;
    }

    public void matchExp() throws DownloadException {
        for (RegExp regExp : subRegExps) {
            regExp.matchExp();
        }
        String outResult = exp.matchExp(replaceBufferValue(input),
                replaceBufferValue(output));
        if (outResult == null || outResult.equals("")) {
            if (exp.clear) {
                scraper.getBuffer()[dest] = "";
            }
        } else {
            outResult = matchSubFuncTag(outResult);
            if (addDest) {
                scraper.getBuffer()[dest] += outResult;
            } else {
                scraper.getBuffer()[dest] = outResult;
            }
        }

    }

    private String matchSubFuncTag(String outResult) throws DownloadException {

        Pattern p = Pattern
                .compile("<url[^>]*?function=\"(\\w+)\"[^>]*>([^<]+)</url>");
        Matcher m = p.matcher(outResult);
        StringBuffer result = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(result,
                    matchSubFuncTag(ResultUrl.urlFactory(m.group(), null)
                            .get(0)));
        }
        m.appendTail(result);
        return result.toString();
    }

    private String matchSubFuncTag(ResultUrl url) throws DownloadException {
        Scraper subFuncScraper = scraper.clonScraper();
        subFuncScraper.setBufferValue(1,
                scraper.getHttpDownload().downloadPage(url.getUrl(), url.getEncodingType()));
        return subFuncScraper.getDefineTag(url.getFunction()).matchRegExp();
    }


    private String replaceBufferValue(String str) {
        // replace param

        Pattern p;// = Pattern.compile("\\$INFO\\[(\\w+?)\\]");
        Matcher m;// = p.matcher(str);
        StringBuffer result ;//= new StringBuffer();
        /*
while (m.find()) {
// if str have $ throw index out bound !!
m.appendReplacement(result, scraper.getParams().get(m.group(1))
       .replace("$", ""));
}
m.appendTail(result);
str = result.toString();
        */
        // replace buffer
        String reg = "\\$\\$(\\d+)";
        p = Pattern.compile(reg);
        if (str.matches("^" + reg + "$")) {
            return scraper.getBuffer()[Integer.parseInt(str.substring(2))];
        }
        m = p.matcher(str);
        result = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(result, scraper.getBuffer()[Integer.parseInt(m
                    .group(1))].replace("$", ""));
        }
        m.appendTail(result);

        return result.toString();
    }
}
